﻿
(function($) {
    window.dataSource = function() { this.initialize.apply(this, arguments); };
    dataSource.prototype = {
        initialize: function(define) {
            jQuery.extend(this, define);
        },
        select: function() { },
        insert: function() { this.onInserted() },
        update: function() { this.onUpdated() },
        dele: function() { $(this.xml).remove(); this.onDeleted() },
        onInserted: function() { },
        onUpdated: function() { },
        onDeleted: function() { }
    };


    window.gridView = function() { this.initialize.apply(this, arguments); };
    gridView.prototype = {
        initialize: function(define) {
            jQuery.extend(this, define);
            this.rowElts = [];
            var thisObj = this;
            jQuery.each(this.dataSource.select(), function() {
                var row = { data: this };
                thisObj.onRowCreating(row);
                thisObj.createRow(row);
                thisObj.onRowCreated(row);
            });
        },
        createRow: function(row) {
        },
        deleteRow: function(row) {
            this.onRowDeleting(row);
            this.dataSource.dele(row);
            this.onRowDeleted(row);
        },
        onRowCreating: function() { },
        onRowCreated: function() { }
    };

    window.formView = function() { this.initialize.apply(this, arguments); };
    formView.prototype = {
        initialize: function(define) {
            jQuery.extend(this, define);
            var thisObj = this;
            this.dataSource.onInserted = function(result) {
                thisObj.mode = "edit";
                $(thisObj.container).removeClass("insert");
                if (result && $("Code", result).text() == "00001") {
                    //$(this.xml).append(treeforms.createNode(thisObj.primekey, this.xml));
                    //$(thisObj.primekey, this.xml).text($("Data", result).text());
                    treeforms.merge(this.xml, $("Data", result).get(0));
                }
                if (thisObj.onInserted) thisObj.onInserted();
                thisObj.hide();
            };
            this.dataSource.onUpdated = function(result) {
                thisObj.grid.rowBind(thisObj.gridRow);
                if (thisObj.onUpdated) thisObj.onUpdated();
                thisObj.hide();
            };
            this.bind();
        },
        show: function() {
            $(this.container).show();
        },
        hide: function() {
            if (this.mode == "edit")
                $(this.container).hide();
            else if (this.mode == "insert")
                this.remove();
        },
        remove: function() {
            if (this.mode == "edit")
                this.dataSource.dele();
            $(this.container).remove();
        },
        bind: function() { },
        commit: function() {
            if (this.mode == "edit")
                this.dataSource.update();
            else if (this.mode == "insert")
                this.dataSource.insert();

            return this.dataSource.xml;
        },
        getPrimekey: function() {
            return $(">" + this.primekey, this.dataSource.xml).text();
        }
    };


    window.createMapping = function(define) {

        var gridData = $(define.grid.path, define.data.container).get(0);
        if (gridData == null) {
            gridData = treeforms.createNode(define.grid.path, define.data.container);
            $(define.data.container).append(gridData);
        }

        var grid = new gridView({
            container: $(define.grid.container, define.container).get(0),
            dataSource: new dataSource({
                xml: gridData,
                select: function() {
                    return $((define.grid.node || define.form.path), this.xml)
                }
            }),
            onRowCreating: function(row) {
                var formElt = createForm($(define.form.container, define.container).get(0));
                row.formView = formElt.formView = new formView({
                    container: formElt, mode: "edit", primekey: define.form.primekey,
                    dataSource: new dataSource({ xml: row.data,
                        update: define.data.update,
                        dele: define.data.dele
                    }),
                    bind: function() {
                        if (this.dataSource.xml == null) {
                            this.dataSource.xml = treeforms.createNode(define.form.path, define.data.container);
                            $(grid.dataSource.xml).append(this.dataSource.xml);
                        }
                        this._bind();
                    },
                    onUpdated: define.form.onUpdated,
                    _bind: define.form.bind
                });
            },
            createRow: function(row) {
                row.element = createRow(this.container);
                row.element.formView = row.formView;
                row.formView.grid = this;
                row.formView.gridRow = row.element;
                this.rowBind(row.element);
                this.rowElts.push(row.element);
                return row.element;
            },
            rowBind: function(element) {
                var rowData = {};
                jQuery.each(define.grid.row || {}, function(name, val) {
                    rowData[name] = $(val, element.formView.container).val();
                });
                jQuery.each(rowData, function(name, val) {
                    if (!jQuery.isFunction(val))
                        $(name, element).text(val);
                });
            }
        });
        $(".open_add_form:first", define.container).click(function() {
            if ($(define.form.container, define.container).find(">.insert").length == 0) {
                var formElt = createForm($(define.form.container, define.container).get(0));
                $(formElt).addClass("insert");
                formElt.formView = new formView({
                    container: formElt, mode: "insert", primekey: define.form.primekey,
                    dataSource: new dataSource({
                        insert: define.data.insert,
                        update: define.data.update,
                        dele: define.data.dele
                    }),
                    bind: function() {
                        if (this.dataSource.xml == null) {
                            this.dataSource.xml = treeforms.createNode(define.form.path, define.data.container);
                            $(grid.dataSource.xml).append(this.dataSource.xml);
                        }
                        this._bind();
                    },
                    _bind: define.form.bind,
                    onInserted: function() {
                        grid.createRow({ formView: this });
                        if (define.form.onInserted) define.form.onInserted.call(this);
                    },
                    onUpdated: define.form.onUpdated
                });
                formElt.formView.show();
            }
        });

        function createRow(container) {
            return $(".template", container).clone()
                .removeClass("template")
                .addClass("row")
                .appendTo($("table", container).get(0))
                .map(function() {
                    var thisObj = this;
                    $(".edit", this).click(function() {
                        thisObj.formView.show();
                    });
                    $(".delete", this).click(function() {
                        with (thisObj.formView) {
                            remove();
                            $(thisObj).remove();
                        }
                    });
                    return this;
                }).get(0);
        }

        function createForm(container) {
            return $(">.template", container).clone().hide()
                 .removeClass("template")
                 .addClass("row")
                 .appendTo(container).map(function() {
                     var thisObj = this;
                     $(">.form_command_panel .update", this).click(function() {
                         with (thisObj.formView) {
                             commit();
                         }
                     });
                     $(">.form_command_panel .cancel", this).click(function() {
                         thisObj.formView.hide();
                     });
                     return this;
                 }).get(0);
        }

        return {
            grid: grid, changes: function() {
                return jQuery.map(grid.rowElts, function(element) {
                    return element.formView.commit();
                });
            }
        };
    }

})(jQuery);